{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Part 1, Topic 1: Introduction to TVLA"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**SUMMARY:** *Up to this point, we've focused on breaking AES implementations with different types of attacks and leakage models. This gives a clear indication as to whether or not a key can be recovered by using power analysis; however, with the many types of attacks and leakage models, it can be difficult to perform. Instead, what if we ask a more generic question: can we detect side channel information via power traces?*\n",
    "\n",
    "*This question, as it turns out, can be much easier to answer. Using the Test Vector Leakage Assessment (TVLA), we can assess a target's vulnerability to power analysis via a generic test. This helps remove much of the complexity from our work.*\n",
    "\n",
    "**LEARNING OUTCOMES:**\n",
    "* Understanding why a TVLA can be used to assess a target's vulnerability to side channel attacks\n",
    "* Understanding limitations and downsides to TVLA\n",
    "* Performing a TVLA test"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## TVLA Theory\n",
    "\n",
    "So, we know the name, but how does this magical test that removes the difficulty from power analysis work? The basic idea is to collect two sets of power traces that we expect to have different means based only on side channel leakage. We can then assess the likelyhood that their means are actually different, or only different due to variance in the power traces. To assess this likelyhood, we'll use Welsh's T-Test:\n",
    "\n",
    "$$\n",
    "t = \\frac{\\bar{X_1} - \\bar{X_2}}{\\sqrt{\\frac{s_1^2}{N_1} + \\frac{s_2^2}{N_2}}}\n",
    "$$\n",
    "\n",
    "What data should we use for our two sets of power traces? A simple set is fixed vs. random text. The first set of data is a constant key and a constant plaintext, giving an on average constant non-zero leakage. The other is a fixed key (the same as the first group) with a random plaintext, giving an average leakage near zero. Rambus has a [document](https://www.rambus.com/wp-content/uploads/2015/08/TVLA-DTR-with-AES.pdf) outlining how to perform TVLA tests. In it, they specify what values to use for the fixed plaintext and key:\n",
    "\n",
    "$$\n",
    "    I_{fixed} = \\texttt{0xda39a3ee5e6b4b0d3255bfef95601890} \\\\\n",
    "    K_{dev} = \\texttt{0x0123456789abcdef123456789abcdef0}\n",
    "$$\n",
    "\n",
    "as well as the random plaintext/fixed key:\n",
    "\n",
    "$$\n",
    "    K_{gen} = \\texttt{0x123456789abcdef123456789abcde0f0} \\\\\n",
    "    I_{0} = \\texttt{0x00000000000000000000000000000000} \\\\\n",
    "    I_{j+1} = \\mathtt{AES(I_{j}, K_{gen})} \\\\\n",
    "    K_{dev} = \\texttt{0x0123456789abcdef123456789abcdef0}\n",
    "$$\n",
    "\n",
    "As a quick test, let's try capturing a bunch of traces and seeing if we can see a difference between the means of the two groups:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "SCOPETYPE = 'OPENADC'\n",
    "PLATFORM = 'CWLITEARM'\n",
    "CRYPTO_TARGET='TINYAES128C' "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%bash -s \"$PLATFORM\" \"$CRYPTO_TARGET\"\n",
    "cd ../../../firmware/mcu/simpleserial-aes\n",
    "make PLATFORM=$1 CRYPTO_TARGET=$2"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%run \"../../Setup_Scripts/Setup_Generic.ipynb\"\n",
    "cw.program_target(scope, prog, \"../../../firmware/mcu/simpleserial-aes/simpleserial-aes-{}.hex\".format(PLATFORM))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "ChipWhisperer includes a random vs. fixed text KTP. It randomly returns text from the two groups, so we'll need to check which one we got to know which group to append the trace to:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "N = 500\n",
    "import numpy as np\n",
    "from tqdm.autonotebook import trange\n",
    "ktp = cw.ktp.TVLATTest()\n",
    "ktp.init(N)\n",
    "\n",
    "group1 = []\n",
    "group2 = []\n",
    "g1_i = 0\n",
    "g2_i = 0\n",
    "for i in trange(2*N, desc='Capturing traces'):\n",
    "    key, text = ktp.next()  # TVLA T-Test changes PT between two options\n",
    "    trace = cw.capture_trace(scope, target, text, key)\n",
    "    if trace is None:\n",
    "        print(\"AHHHHHHHHHH\")\n",
    "        continue\n",
    "    if trace.textin == bytearray([0xda, 0x39, 0xa3, 0xee, 0x5e, 0x6b, 0x4b, 0x0d, 0x32, 0x55, 0xbf, 0xef, 0x95, 0x60, 0x18, 0x90]):\n",
    "        group1.append(trace.wave)\n",
    "        g1_i += 1\n",
    "    else:\n",
    "        group2.append(trace.wave)\n",
    "        g2_i += 1\n",
    "        \n",
    "group1 = np.array(group1)\n",
    "print(len(group1))\n",
    "group2 = np.array(group2)\n",
    "print(len(group2))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The mean of the two groups can be easily taken by numpy:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "mean1 = np.mean(group1, axis=0)\n",
    "mean2 = np.mean(group2, axis=0)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "cw.plot(mean2) * cw.plot(mean1)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We can't really see much from the above plot. After all, the part of the power trace that corresponds to data leakage is very small. Let's try subtracting the means from each other to see if there's a clear difference:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "cw.plot(mean1- mean2)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "This answer appears to be: maybe! You might be able to pick out a repeated pattern (which makes sense for the 10 rounds of AES128), but it probably also looks quite noisy. Is the differences we're seeing from variance in the data, or is really a difference in mean between the two groups? Let's try running the T-Test (scipy has a function for calculating this) on this group of data:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from scipy.stats import ttest_ind\n",
    "t_val = ttest_ind(group1, group2, axis=0, equal_var=False)[0]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "cw.plot(t_val)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now, how do we interpret this data? The value returned by the T-Test is actually a significance (think bell curve), so a value of only 4.5 (which is typically used as a success measurement for TVLA) will correspond to a probabiltiy of $6.8\\times10^{-4}\\%$ chance that the difference in means is due to variance.\n",
    "\n",
    "We can get a better test if we split each group in half and run 2 T-Tests. If $|t| \\geq \\pm4.5$ for both tests at the same point (both t must have the same sign), the device can be considered to have failed the TVLA.\n",
    "\n",
    "Let's see what this looks like. While we're at it, let's plot our $\\pm4.5$ bounds as well:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import holoviews as hv\n",
    "N = len(group1)\n",
    "t_val = [ttest_ind(group1[:N//2], group2[:N//2], axis=0, equal_var=False)[0], \n",
    "         ttest_ind(group1[N//2:], group2[N//2:], axis=0, equal_var=False)[0]]\n",
    "\n",
    "cv = cw.plot(t_val[0]) * cw.plot(t_val[1])\n",
    "cv *= cw.plot([4.5]*len(group1[0]))\n",
    "cv *= cw.plot([-4.5]*len(group1[0]))\n",
    "cv"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "As expected, this very weak software implementation of AES easily fails, with many excursions beyond $\\pm4.5$"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Further Reading\n",
    "\n",
    "The original specification for TVLA is available at: https://csrc.nist.gov/csrc/media/events/non-invasive-attack-testing-workshop/documents/08_goodwill.pdf. It has additional background and theory on the data used in TVLA and the T-Test evaluation.\n",
    "\n",
    "The Rambus document also has additional non-specific datasets desribed, such as random vs. fixed key, and semi-fixed vs. random text. Another type of dataset it describes is the specific dataset, which we'll discuss in a later tutorial."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.9.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
